日期问题

分析

格式化输入输出

用scanf读入

使用scanf("%d/%d/%d", &a, &b, &c); 在02/03/03这样的输入中提取到02 03 04这几个值

scanf("%04d%02d%02d", &year, &month, &day); 将8位数自动处理到年月日

用printf输出

printf("%d-%02d-%02d\n", year, month, day); 可以将9月输出为09 原理是输出占两位 不足用0填补

sprintf(s,"%04d%02d%02d",y,m,d); 将年月日读入到字符串里面去 直接可以对字符串进行处理

筛日期

一个很常用的技巧 要什么日期 首先先把这段时间的合法的日期全都找出来 然后再对他们进行操作 类似于筛素数 先筛再操作

筛选也很简单 将日期用八位数表示 从起始到结束循环就行了 不用考虑多少进位的问题 多枚举那点不算什么

for (int date = Start; date <= End; date ++ ){

int year = date / 10000, month = date % 10000 / 100, day = date % 100;

if (check_valid(year, month, day))

……

}

}

如何判断是否是合法日期呢

首先年份没什么可看的 基本没什么限制

月份要是0~12

天数就比较复杂 用一个数组记录每个月应该有的天数

int days[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

然后首先就是要在0~31的范围内

其次就是与某月应该有的天数进行比较 这里二月比较特殊 还要另外判断一个闰年

四年一闰:年份是4的倍数是闰年;

百年不闰:是100的倍数不是闰年;

四百年又闰:是400的倍数却又是闰年。

if(year % 100 && year % 4 <mark> 0 || year % 400 </mark> 0)

bool check_date(int year, int month, int day){

if (month == 0 || month > 12)

return false;

if (day == 0 || day > 31)

return false;

int curdays=days[month];

if(month==2)

if(year % 100 && year % 4 <mark> 0 || year % 400 </mark> 0)

curdays+=1;

if(day>curdays)

return false;

return true;

}

这种方式 泛用性也更强了

#include<bits/stdc++.h>
using namespace std;

int days[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};

bool check_date(int year,int month,int day){
    if(month==0 || month>12)
        return false;
    if(day==0 || day>31)
        return false;
    int curdays=days[month];
    if(month==2)
        if(year%100 && year%4==0 && year%400==0)
            curdays++;
    if(day>curdays)
        return false;
    return true;
}

int main()
{
    int one,two,three;
    scanf("%d/%d/%d",&one,&two,&three);
    cin>>Start>>End;
    for(int date=Start;date<=End;date++){
        int year=date/10000; //取前4位(砍掉后4位) / 4个0
        int month=date%10000/100;//取后4位 %4个0 取后4位的前2位 再砍去2个0
        int day=date%100; //取后2位 直接 %2个0
        if(check_date(year,month,day)){
            //具体逻辑
            //…………
            printf("%d-%02d-%02d\n", year, month, day);
        }
    }
    return 0;
}

算相差天数

类似于前缀和的思想

image-27614fe9

分别计算两个日期距离一个公元1年1月1日的总天数

然后计算这两个天数之间的差值来得到日期差

注意考虑闰年对2月天数的影响

#include<bits/stdc++.h>
using namespace std;

int days[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

bool isLeapYear(int year) {
    return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}

// 计算从公元1年1月1日到指定日期的总天数
int daysFromStart(int year, int month, int day) {
    int totalDays = 0;
    // 添加之前年份的天数
    for(int y = 1; y < year; y++) {
        totalDays += isLeapYear(y) ? 366 : 365;
    }
    // 添加当前年份的月份天数
    for(int m = 1; m < month; m++) {
        totalDays += days[m];
        if(m == 2 && isLeapYear(year)) {
            totalDays++;
        }
    }
    // 添加当前月份的天数
    totalDays += day;

    return totalDays;
}

int main() {
    int startDate, endDate;
    while(cin >> startDate >> endDate) {

        if(startDate>endDate)
            swap(startDate,endDate);

        int startYear=startDate/10000,
            startMonth=startDate%10000/100,
            startDay=startDate%100;

        int endYear=endDate/10000,
            endMonth=endDate%10000/100,
            endDay=endDate%100;

        int dateDiff = daysFromStart(endYear,endMonth,endDay)
                     - daysFromStart(startYear,startMonth,startDay)
                     + 1;

        cout << dateDiff << endl;
    }
    return 0;
}

*组合拳

写日期问题 把这几个函数一默写上 后面就基本不成问题了

int days[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

bool is_leap(int y){
    return y%100 && y%4==0 || y%400==0;
}

int get_days(int y,int m){
    return days[m]+(m==2 && is_leap(y));
}

void next_day(int &y,int &m,int &d){//注意 传的是引用
    d++;
    if(d>get_days(y,m)){
        d=1;
        m++;
        if(m>12){
            m=1;
            y++;
        }
    }
}

bool check_date(int y, int m, int d) {
    if (m < 1 || m > 12)
          return false;
    if(d < 1 || d > getdays(y,m))
          return false;
    return true;
}

while ((curYear < 给定年份) ||
       (curYear == 给定年份 && curMonth < 给定月份) ||
       (curYear == 给定年份 && curMonth == 给定月份 && curDay < 给定日子)) {
    // 执行 next_day 操作
}

题目

https://www.acwing.com/blog/content/24163/


⬅️ 打酱油 🏠 00-刷题理模型 ➡️ 回文日期